package org.jeecg.modules.friends.base;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jeecg.modules.friends.service.impl.LCD;
import org.jeecg.modules.friends.utils.ServerTool;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Description:
 *
 * @Date Create on 2022/6/19
 */
@Slf4j
public class NotifyTool {
    private static String alarmGroup =
            "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=754bcfcf-847d-49c7-aacc-9789e756465e";
    private static Map<String, String> mapsAlarmGroup = Maps.newHashMap();

    static {
        mapsAlarmGroup.put("alarmGroup", alarmGroup);
        mapsAlarmGroup.put("举报群",
                "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=2332f158-b900-4f86-86b6-abd9d9a58c3f");
    }

    public static void weChat(String content, String groupNotifyUrl) {
        ThreadPoolTool.execute(() -> {
            sendWeChatFirmMarkdown(content, groupNotifyUrl);
        });
    }

    public static void asyncWeChatImage(InputStream in, String groupNotifyUrl) {
        ThreadPoolTool.execute(() -> {
            sendWeChatFirmImage(in, groupNotifyUrl);
        });
    }

    public static void weChatAlarm(String content) {
        weChatAlarm(content, "");
    }

    public static void weChatAlarm(String content, String groupName) {
        List<String> filterKeyWords = JsonTool.parseArray(LCD.getContentDefault(99990011, "[]"), String.class);
        if (filterKeyWords.stream().anyMatch(content::contains)) {
            return;
        }
        ThreadPoolTool.execute(() -> {
            String ipPort = SpringUtil.getBean(Environment.class).getProperty("server.port");
            String alarmMsg = "## " + ServerTool.getServerName() + "-" + ipPort + "\n"
                    + "```\n"
                    + "" + content + "\n"
                    + "```";
            sendWeChatFirmMarkdown(alarmMsg, mapsAlarmGroup.getOrDefault(groupName, alarmGroup));
        });
    }

    public static void emailByOfficial(List<String> addressList, String title, String content, File file) {
        if (!SystemUtil.getOsInfo().isLinux()) {
            return;
        }
        sendEmail(getSendUserList(), addressList, title, content, file);
    }

    public static void weChatAlarm(Exception e) {
        weChatAlarm(ExceptionUtils.getStackTrace(e));
    }

    public static void emailAnWechatAlarm(Exception e) {
        weChatAlarm(e);
        emailAlarm(e.getMessage());
    }

    public static void emailAlarm(String content) {
        ThreadPoolTool.execute(() -> {
            String ipPort = SpringUtil.getBean(Environment.class).getProperty("server.port");
            emailAlarm(Lists.newArrayList("itfangwei@foxmail.com"), "alarm-" + ipPort,
                    content);
        });
    }

    public static void emailAlarm(Exception e) {
        emailAlarm(ExceptionUtils.getStackTrace(e));
    }


    private static void sendWeChatFirmMarkdown(String content, String url) {
        if (!SystemUtil.getOsInfo().isLinux()) {
            return;
        }
        CommonNotifyBO commonNotifyBO = new CommonNotifyBO();
        commonNotifyBO.setMsgtype("markdown");
        Markdown markdown = new Markdown();
        markdown.setContent(content);
        commonNotifyBO.setMarkdown(markdown);
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(commonNotifyBO));
        Request request = new Request.Builder()
                .url(url)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .build();
        try {
            Response response = client.newCall(request).execute();
            Assert.notNull(response.body());
            log.info("sendWeChatCom :{}", response.body().string());
        } catch (Exception e) {
            log.error("sendWeChatCom error. req:{}-{}", content, url, e);
            emailAlarm(e.getMessage() + content);
        }
    }

    //https://developer.work.weixin.qq.com/document/path/91770#%E5%9B%BE%E7%89%87%E7%B1%BB%E5%9E%8B
    private static void sendWeChatFirmImage(InputStream in, String url) {
        if (!SystemUtil.getOsInfo().isLinux()) {
            return;
        }
        String md5 = null;
        try {
            byte[] imageBytes = IoUtil.readBytes(in);

            String imageBase64Str = Base64.getEncoder().encodeToString(imageBytes)
                    .replaceAll("[\r\n]", "");

            md5 = MD5.create().digestHex(imageBytes);

            Map<String, Object> notifyMap = Maps.newHashMap();
            notifyMap.put("msgtype", "image");
            Map<String, Object> imageMap = Maps.newHashMap();
            imageMap.put("base64", imageBase64Str);
            imageMap.put("md5", md5);
            notifyMap.put("image", imageMap);
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .build();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(notifyMap));
            Request request = new Request.Builder()
                    .url(url)
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            Response response = client.newCall(request).execute();
            Assert.notNull(response.body());
            log.info("sendWeChatFirmImage req md5:{} :{}", md5, response.body().string());
        } catch (Exception e) {
            log.error("sendWeChatFirmImage error. req:{}", md5, e);
            emailAlarm(e.getMessage());
        }
    }

    private static List<SendUser> getSendUserList() {
        return JsonTool.parseArray(LCD.getContentDefault(99990007, "[]"), SendUser.class);
    }

    private static List<SendUser> getAlarmSendUserList() {
        SendUser sendUser = new SendUser();
        sendUser.setHost("smtp.exmail.qq.com");
        sendUser.setPort(465);
        sendUser.setFrom("alarm@yka8.wecom.work");
        sendUser.setUser("");
        sendUser.setPass("JcgVEfNAJ5RDKGWf");
        return Lists.newArrayList(sendUser);
    }


    private static void emailAlarm(List<String> addressList, String title, String content) {
        if (!SystemUtil.getOsInfo().isLinux()) {
            return;
        }
        sendEmail(getAlarmSendUserList(), addressList, title, content, null);
    }


    private static void sendEmail(List<SendUser> sendUserList, List<String> addressList, String title,
            String content, File file) {
        System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
        System.setProperty("mail.mime.charset", "UTF-8");
        int sendCount = 0;
        SendUser sendUser = null;
        for (; ; ) {
            try {
                int index = RandomUtil.randomInt(0, sendUserList.size());
                sendUser = sendUserList.get(index);
                MailAccount account = new MailAccount();
                account.setHost(sendUser.getHost());
                account.setPort(sendUser.getPort());
                account.setAuth(true);
                account.setFrom(sendUser.getFrom());
                account.setUser(sendUser.getUser());
                account.setPass(sendUser.getPass());
                account.setCharset(StandardCharsets.UTF_8);
                account.setSslEnable(true);
                account.setSocketFactoryClass("javax.net.ssl.SSLSocketFactory");
                account.setSocketFactoryFallback(true);
                account.setSocketFactoryPort(sendUser.getPort());
                if (file != null) {
                    MailUtil.send(account, addressList, title, "请查看附件~", true, file);
                    log.info("邮件发送成功，发送账号:{} , 接收方:{}", sendUser.getFrom(),
                            JSON.toJSONString(addressList));
                }
                if (StrUtil.isNotBlank(content)) {
                    MailUtil.send(account, addressList, title, content, true);
                }
                log.info("邮件发送成功，发送账号:{} , 接收方:{}", sendUser.getFrom(),
                        JSON.toJSONString(addressList));
                break;
            } catch (Exception e) {
                ++sendCount;
                log.info("账号{}发送失败,error msg:{}", JSON.toJSONString(sendUser), e.getMessage());
                if (sendCount > 10) {
                    log.warn("连续发送10次失败 sendEmailOfficial error ，发送账号：{} ,接收方:{}，error msg:{}", sendUser.getFrom(),
                            JSON.toJSONString(addressList), e.getMessage());
                    weChatAlarm(
                            "连续发送10次失败 sendEmailOfficial error . 发送账号: " + sendUser.getFrom() + ", 接收方：" + JSON
                                    .toJSONString(addressList));
                    break;
                }
            }
        }

    }

    public static void main(String[] args) {
        Map<String, Object> notifyMap = Maps.newHashMap();
        notifyMap.put("msgtype", "image");
        Map<String, Object> imageMap = Maps.newHashMap();
        imageMap.put("base64", "123123");
        imageMap.put("md5", "!23123");
        notifyMap.put("image", imageMap);
        System.out.println(JSON.toJSONString(notifyMap));

    }
}
